﻿//MarketDataBuffer.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.Storages
{
	using System;
	using System.Collections.Generic;
	using System.Linq;

	using Ecng.Collections;

	using StockSharp.BusinessEntities;

	/// <summary>
	/// Буфер маркет-данных.
	/// </summary>
	/// <typeparam name="TMarketData">Тип маркет-данных.</typeparam>
	public class MarketDataBuffer<TMarketData>
	{
		private readonly SynchronizedDictionary<Security, List<TMarketData>> _data = new SynchronizedDictionary<Security, List<TMarketData>>();

		/// <summary>
		/// Размер буфера.
		/// </summary>
		public int Size { get; set; }

		/// <summary>
		/// Добавить новую информацию в буфер.
		/// </summary>
		/// <param name="security">Инструмент, которому принадлежит новая информация.</param>
		/// <param name="data">Новая информация.</param>
		public void Add(Security security, TMarketData data)
		{
			Add(security, new[]{ data });
		}

		/// <summary>
		/// Добавить новую информацию в буфер.
		/// </summary>
		/// <param name="security">Инструмент, которому принадлежит новая информация.</param>
		/// <param name="data">Новая информация.</param>
		public void Add(Security security, IEnumerable<TMarketData> data)
		{
			_data.SyncDo(d => d.SafeAdd(security).AddRange(data));
		}

		/// <summary>
		/// Получить накопленные данные из буфера и удалить их.
		/// </summary>
		/// <returns>Полученные данные.</returns>
		public IDictionary<Security, IEnumerable<TMarketData>> Get()
		{
			return _data.SyncGet(d =>
			{
				var retVal = d.ToDictionary(p => p.Key, p => (IEnumerable<TMarketData>)p.Value);
				d.Clear();
				return retVal;
			});
		}

		/// <summary>
		/// Получить накопленные данные из буфера и удалить их.
		/// </summary>
		/// <param name="security">Инструмент, которому принадлежат маркет-данных.</param>
		/// <returns>Полученные данные.</returns>
		public IEnumerable<TMarketData> Get(Security security)
		{
			if (security == null)
				throw new ArgumentNullException("security");

			return _data.SyncGet(d =>
			{
				var data = d.TryGetValue(security);

				if (data != null)
				{
					var retVal = data.CopyAndClear();
					d.Remove(security);
					return retVal;
				}

				return Enumerable.Empty<TMarketData>();
			});
		}
	}
}